﻿using System;
using System.Xml;
using System.ComponentModel;
using System.Threading;
using Android.Graphics.Drawables.Shapes;
using Android.Widget;
using Android.App;
using Android.Views;
using Android.Graphics;
using Android.Util;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
using System.Reflection;
using UnitDriven.Commanding;

namespace UnitDriven
{
#region " TestListAdapter "
  public class TestListAdapter : BaseAdapter
  {
  #region " Declarations "
    MainActivity _activity;
    private List<IRunTests> _items = new List<IRunTests>();
    private List<TestResult> _currentResults = new List<TestResult>();
    private CommandQueue _commandQueue = CommandQueue.Instance;
  #endregion

  #region " Constructors "
    public TestListAdapter(MainActivity context, TestContext myContext)
      : base()
    {
      this._activity = context;

      foreach (TestGroup testGroup in myContext.Items)
      {
        _items.Add(testGroup);
        testGroup.PropertyChanged += (o, e) => OnPropertyChangedListener(o, e);
        _currentResults.Add(testGroup.Status);
        foreach (TypeTester typeTester in testGroup.Items)
        {
          _items.Add(typeTester);
          typeTester.PropertyChanged += (o, e) => OnPropertyChangedListener(o, e);
          _currentResults.Add(typeTester.Status);
          foreach (MethodTester methodTester in typeTester.Items)
          {
            _items.Add(methodTester);
            methodTester.PropertyChanged += (o, e) => OnPropertyChangedListener(o, e);
            _currentResults.Add(methodTester.Status);
            methodTester.PropertyChanged += (sender, e) => { context.PropertyChanged(sender, e); };
          }
        }
      }
    }
  #endregion

  #region " Overrides "
    public override int Count
    {
      get { return _items.Count; }
    }

    public override Java.Lang.Object GetItem(int position)
    {
      return position;
    }

    public override long GetItemId(int position)
    {
      return position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
      ViewHolder holder;

      IRunTests item = _items[position];

      if (convertView == null)
      {
        convertView = _activity.LayoutInflater.Inflate(Resource.Layout.TestListItem, parent, false) as LinearLayout;
        //item.Layout = (LinearLayout)convertView;
        holder = new ViewHolder();
        holder.btnStatus = (StatusButton)convertView.FindViewById(Resource.Id.imgStatus);
        holder.lblIndent = (TextView)convertView.FindViewById(Resource.Id.lblIndent);
        holder.lblTest = (TextView)convertView.FindViewById(Resource.Id.lblTest);
        holder.btnError = (Button)convertView.FindViewById(Resource.Id.btnError);
        convertView.Tag = holder;
        holder.btnStatus.Click += (o, e) => OnStatusClickListener(o, e);
      }
      else
      {
        holder = (ViewHolder)convertView.Tag;
      }

      //Assign this item's values to the various subviews
      try
      {
        holder.position = position;
        //Check to see if Click event has a handler assigned


        holder.lblIndent.Text = GetIndent(item);
        holder.lblTest.SetText(GetDisplayName(item), TextView.BufferType.Normal);

        holder.btnStatus.StatusColor = GetColor(item.Status);

        if (item.Status == TestResult.Fail && item is MethodTester)
        {
          holder.btnError.Visibility = Android.Views.ViewStates.Visible;

          holder.btnError.Click -= OnErrorClickListener;
          holder.btnError.Click += (o, e) => OnErrorClickListener(o, e);
        }
        else
        {
          holder.btnError.Visibility = Android.Views.ViewStates.Gone;
        }

      }
      catch (Exception ex)
      {
        convertView = GetView(position, null, parent);
        Toast.MakeText(_activity, ex.ToString(), ToastLength.Long).Show();
        Log.Error("TestListItem.GetView", ex.ToString());
      }

      //Finally return the view
      return convertView;
    }
  #endregion

  #region " Methods "
    private string GetIndent(IRunTests item)
    {
      int indent = 0;
      if (item is TestGroup) { indent = 1; }
      else if (item is TypeTester) { indent = 2; }
      else { indent = 3; }
      return String.Concat(Enumerable.Repeat("\t", indent)); 
    }

    private string GetDisplayName(IRunTests item)
    {
      if (item is TypeTester) { return "Type:\t" + item.Name; }
        else { return item.Name; }
    }

    private Color GetColor(TestResult status)
    {
      switch (status)
      {
        case TestResult.Indeterminate:
          return Color.Yellow;
        case TestResult.Success:
          return Color.Green;
        case TestResult.Fail:
          return Color.Red;
        case TestResult.Evaluating:
          return Color.DarkGray;
        default:
          return Color.LightGray;
      }
    }

    private IRunTests GetTestRunner(object o)
    {
        View sb = (View)o;
        LinearLayout ll = (LinearLayout)sb.Parent;
        ViewHolder viewHolder = (ViewHolder)ll.Tag;

        return (IRunTests)_items[viewHolder.position];
    }
  #endregion

  #region " Event Handlers "
    private void OnErrorClickListener(object o, EventArgs e)
    {
      try
      {
        //Error button only appears on MethodTester objects
        MethodTester item = (MethodTester)GetTestRunner(o);

        _activity.SetContentView(Resource.Layout.ErrorDetails);

        TextView lblErrorText = (TextView)_activity.FindViewById(Resource.Id.lblErrorText);

        lblErrorText.Text = item.Message;

        Button btnBack = (Button)_activity.FindViewById(Resource.Id.btnBack);

        btnBack.Click += (a, b) => { OnBackClickListener(a, b); };
      }
      catch (Exception ex)
      {
        Log.Error("TestListItem.OnErrorClickListener", ex.ToString());
        Toast.MakeText(_activity, "Error Occured!" + ex.ToString(), ToastLength.Long);
      }
    }

    private void OnStatusClickListener(object o, EventArgs e)
    {
      try
      {
        IRunTests item = GetTestRunner(o);
        item.RunTests();
      }
      catch (Exception ex)
      {
        Log.Error("TestListItem.OnStatusClickListener", ex.ToString());
        Toast.MakeText(_activity, "Error Occured!" + ex.ToString(), ToastLength.Long);
      }
    }

    private void OnBackClickListener(object o, EventArgs e)
    {
      try
      {
        _activity.SetContentView(Resource.Layout.TestEngine);
        _activity.HookEventsToView();
        _activity.RefreshCompletedCount();
      }
      catch (Exception ex)
      {
        Log.Error("TestListItem.OnBackClickListener", ex.ToString());
        Toast.MakeText(_activity, "Error Occured!" + ex.ToString(), ToastLength.Long);
      }
    }

    private void OnPropertyChangedListener(object o, PropertyChangedEventArgs e)
    {
      try
      {

        if (e.PropertyName == "Status")
        {
          IRunTests item = (IRunTests)o;
          TestResult currentResult = _currentResults[_items.IndexOf(item)];

          if (currentResult != item.Status)
          {
            _currentResults[_items.IndexOf(item)] = item.Status;
            _activity.RunOnUiThread(() => NotifyDataSetChanged());
          }
        }
      }
      catch (Exception ex)
      {
        Log.Error("TestListItem.OnPropertyChangedListener", ex.ToString());
        Toast.MakeText(_activity, "Error Occured!" + ex.ToString(), ToastLength.Long);
      }
    }

  #endregion
  }
#endregion

#region " ViewHolder "
  public class ViewHolder : Java.Lang.Object 
  {
    public int position;
    public StatusButton btnStatus;
    public TextView lblTest;
    public TextView lblIndent;
    public Button btnError;
  }
#endregion
}
